package com.ruoyi.common.utils.poi.word.render;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.io.FileUtil;
import com.aspose.words.Document;
import com.aspose.words.DocumentBuilder;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.poi.AsposeWordUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.expression.ExpressionException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * word 数据渲染
 */
@Data
@Slf4j
public class WordRenderHandler implements RenderHandler {
    protected StopWatch stopWatch;
    /**
     * 核心业务对象
     */
    protected Object object;
    /**
     * 渲染数据
     */
    protected Map<String, Object> renderedData = new HashMap<>();
    /**
     * 模版路径
     */
    protected String templatePath;
    /**
     * html 内容
     */
    protected String pdfPath;
    /**
     * pdf url
     */
    protected String pdfUrl;
    /**
     * 文件名称
     */
    protected String docName;
    /**
     * word 最终存储路径
     */
    protected String wordPath;
    /**
     * word url
     */
    protected String wordUrl;
    /**
     * 最终存储目录
     */
    protected String fileDir;
    /**
     * 文书数据传输类
     */
    protected TemplateEnum templateEnum;


    protected XWPFDocument document;

    protected XWPFTemplate template;

    /**
     * 增加数据
     */
    public void add(String key, Object val) {
        if (val == null) {
            val = "";
        }
        renderedData.put(key, val);
    }

    @Override
    public void init(TemplateEnum templateEnum) {
        this.stopWatch = new StopWatch();
        this.templatePath = RuoYiConfig.getTemplatePath() + templateEnum.getPath();
        String fileName = FileUploadUtils.extractFilename("docx");
        this.wordPath = RuoYiConfig.getUploadPath() + "/" + fileName;
        this.pdfPath = this.wordPath.replace(".docx", ".pdf");
        this.docName = templateEnum.getValue();
        this.wordUrl = RuoYiConfig.getUploadBasePath() + Constants.RESOURCE_PREFIX + "/upload/" + fileName;
        this.pdfUrl = RuoYiConfig.getUploadBasePath() + Constants.RESOURCE_PREFIX + "/upload/"
                + fileName.replace(".docx", ".pdf");
        System.out.println(this.pdfUrl);
    }

    @Override
    public void makeData() throws IOException {
        this.renderedData.put("date", DateUtil.format(DateUtil.date(), "yyyy年MM月dd日"));
    }

    /**
     * 基本数据填充
     */
    public void render() throws Exception {
        stopWatch.start("任务 - render");
        log.info("任务 - render");
        AsposeWordUtil.getLicense();

        log.info("任务 - render - AsposeWordUtil.getLicense()");
        // Create Document object and initialize with DOCX template.

        ConfigureBuilder builder = Configure.builder();
        builder.setValidErrorHandler(new Configure.DiscardHandler());
        BeanUtils.setLoopRowTableRenderPolicy(renderedData, "", builder);
        builder.useSpringEL();
        try {
            BeanUtils.formatMapNullValue(renderedData);
            template = XWPFTemplate.compile(templatePath, builder.build());
            template.render(renderedData);
        } catch (Exception e) {
            if (template != null) {
                template.close();
            }
            if (e.getCause() instanceof ExpressionException) {
                ExpressionException evaluationException = (ExpressionException) e.getCause();
                throw new Exception(templatePath + "\n" + evaluationException.toDetailedString());
            } else {
                throw e;
            }
        }
        document = template.getXWPFDocument();
        System.out.println(this.wordPath);
        stopWatch.stop();
        stopWatch.prettyPrint();
    }

    @Override
    public void handlePdf() throws Exception {
        render();
        renderPoiDataDoc();
        toWord();
        renderPoiDataWord();
        AsposeWordUtil.wordToPdf(wordPath, pdfPath);
        renderAfter();
        document.close();
    }

    @Override
    public void renderAfter() throws Exception {

    }

    @Override
    public void makeSignUser() {

    }

    @Override
    public void buildEnterpriseFile() {

    }


    /**
     * 渲染图片、html ，在转成word之前。
     */
    private void renderPoiDataDoc() throws Exception {
        Iterator<String> keyIt = renderedData.keySet().iterator();
        while (keyIt.hasNext()) {
            String key = keyIt.next();
            Object val = renderedData.get(key);
            if (!(val instanceof PoiDataBeforeCreateWord)) {
                continue;
            }
            PoiDataBeforeCreateWord poiDataDoc = (PoiDataBeforeCreateWord) val;
            poiDataDoc.handle(document);
        }
    }

    /**
     * 渲染 table ，在转成word之后。
     */
    private void renderPoiDataWord() throws Exception {
        Iterator<String> keyIt = renderedData.keySet().iterator();
        Document doc = new Document(wordPath);
        DocumentBuilder builder = new DocumentBuilder(doc);
        while (keyIt.hasNext()) {
            String key = keyIt.next();
            Object val = renderedData.get(key);
            if (!(val instanceof PoiDataAfterCreateWord)) {
                continue;
            }
            PoiDataAfterCreateWord poiDataWord = (PoiDataAfterCreateWord) val;
            poiDataWord.handle(builder);
        }
        doc.save(wordPath);

        InputStream in = new FileInputStream(wordPath);
        document = new XWPFDocument(in);
    }

    private void toWord() throws IOException {
        FileUtil.mkParentDirs(this.wordPath);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(this.wordPath);
            template.write(out);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
            template.close();
        }
    }

    /**
     * 设置核心业务对象
     */
    public void setObject(Object object) {
        this.object = object;
    }



    /**
     * 添加业务部门签名图片

    protected void addBusinessSignImg(String roleFlag, ActivityScore activityScore){
        BusinessSignMapper businessSignMapper = SpringUtil.getBean(BusinessSignMapper.class);
        ActivityExtractRecordMapper activityExtractRecordMapper = SpringUtil.getBean(ActivityExtractRecordMapper.class);
        ActivityExtractRecord extractRecord = activityExtractRecordMapper.findByActivityIdAndExpertId(activityScore.getActivityId(), activityScore.getExpertId());
        BusinessSign sign = businessSignMapper.findByBusinessAndBusinessIdAndRole(BusinessConstant.SignBusinessType.ACTIVITY_SCORE,
                extractRecord.getActivityGroupId(), roleFlag);

        if(sign != null && sign.getSignImgPath() != null && FileUtil.exist(sign.getSignImgPath())){
            this.add(roleFlag, Pictures.ofLocal(sign.getSignImgPath()).size(140, 70).create());
        }else{
            //this.add(roleFlag, Pictures.ofLocal(RuoYiConfig.getProfile() + "/default/sign.png").size(140, 70).create());
            this.add(roleFlag, Pictures.ofLocal(RuoYiConfig.getTemplatePath() + "/default_sign.png").size(140, 70).create());
        }
    }*/
}
